home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-04 / memos.zip / FILEIO.PRG < prev    next >
Text File  |  1993-03-10  |  9KB  |  359 lines

  1. /***
  2. *
  3. *  Fileio.prg
  4. *  Sample user-defined functions to process binary files
  5. *  Copyright, Nantucket Corporation, 1990
  6. *
  7. *  NOTE: compile with /n/w/a/m
  8. */
  9.  
  10. #include "Fileio.ch"
  11.  
  12. /***
  13. *  FGets( <nHandle>, [<nLines>], [<nLineLength>], [<cDelim>] ) --> cBuffer
  14. *  Read one or more lines from a text file
  15. *
  16. */
  17. FUNCTION FGets(nHandle, nLines, nLineLength, cDelim)
  18.     RETURN FReadLn(nHandle, nLines, nLineLength, cDelim)
  19.  
  20. /***
  21. *  FPuts( <nHandle>, <cString>, [<nLength>], [<cDelim>] ) --> nBytes
  22. *  Write a line to a text file
  23. *
  24. */
  25. FUNCTION FPuts(nHandle, cString, nLength, cDelim)
  26.    RETURN FWriteLn(nHandle, cString, nLength, cDelim)
  27.  
  28. /***
  29. *  DirEval( <cMask>, <bAction> ) --> aArray
  30. *  Apply a code block to each file matching a skeleton
  31. *
  32. *  Tim Wong
  33. */
  34. FUNCTION DirEval( cMask, bAction )
  35.    RETURN AEVAL( DIRECTORY(cMask), bAction )
  36.  
  37. /***
  38. *  FileTop( <nHandle> ) --> nPos
  39. *  Position the file pointer to the first byte in a binary file and return
  40. *  the new file position (i.e., 0).
  41. *
  42. */
  43. FUNCTION FileTop(nHandle)
  44.     RETURN FSEEK(nHandle, 0)
  45.  
  46. /***
  47. *  FileBottom( <nHandle> ) --> nPos
  48. *  Position the file pointer to the last byte in a binary file and return
  49. *  the new file position
  50. *
  51. */
  52. FUNCTION FileBottom(nHandle)
  53.     RETURN FSEEK(nHandle, 0, FS_END)
  54.  
  55. /***
  56. *  FilePos( <nHandle> ) --> nPos
  57. *  Report the current position of the file pointer in a binary file
  58. *
  59. */
  60. FUNCTION FilePos(nHandle)
  61.     RETURN FSEEK(nHandle, 0, FS_RELATIVE)
  62.  
  63. /***
  64. *  FileSize( <nHandle> ) --> nBytes
  65. *  Return the size of a binary file
  66. *
  67. */
  68. FUNCTION FileSize( nHandle )
  69.    LOCAL nCurrent, nLength
  70.  
  71.    // Get file position
  72.    nCurrent := FilePos(nHandle)
  73.  
  74.    // Get file length
  75.    nLength := FSEEK(nHandle, 0, FS_END)
  76.  
  77.    // Reset file position
  78.    FSEEK(nHandle, nCurrent)
  79.  
  80.    RETURN nLength
  81.  
  82. /***
  83. *  FReadLn( <nHandle>, [<nLines>], [<nLineLength>], [<cDelim>] ) --> cLines
  84. *  Read one or more lines from a text file
  85. *
  86. *  NOTE: Line length includes delimiter, so max line read is 
  87. *        (nLineLength - LEN( cDelim ))
  88. *
  89. *  NOTE: Return value includes delimiters, if delimiter was read
  90. *
  91. *  NOTE: nLines defaults to 1, nLineLength to 80 and cDelim to CRLF
  92. *
  93. *  NOTE: FERROR() must be checked to see if FReadLn() was successful
  94. *
  95. *  NOTE: FReadLn() returns "" when EOF is reached
  96. *
  97. */
  98. FUNCTION FReadLn( nHandle, nLines, nLineLength, cDelim )
  99.    LOCAL nCurPos, nFileSize, nChrsToRead, nChrsRead
  100.    LOCAL cBuffer, cLines
  101.    LOCAL nCount
  102.    LOCAL nEOLPos
  103.  
  104.    IF nLines == NIL
  105.       nLines := 1
  106.    ENDIF
  107.  
  108.    IF nLineLength == NIL
  109.       nLineLength := 80
  110.    ENDIF
  111.  
  112.    IF cDelim == NIL
  113.       cDelim := CHR(13) + CHR(10)
  114.    ENDIF
  115.  
  116.    nCurPos   := FilePos( nHandle )
  117.    nFileSize := FileSize( nHandle )
  118.  
  119.    // Make sure no attempt is made to read past EOF
  120.    nChrsToRead := MIN( nLineLength, nFileSize - nCurPos )
  121.  
  122.    cLines  := ''
  123.    nCount  := 1
  124.    DO WHILE (nCount <= nLines) .AND. ( nChrsToRead != 0 ) 
  125.       cBuffer   := SPACE( nChrsToRead )
  126.       nChrsRead := FREAD( nHandle, @cBuffer, nChrsToRead )
  127.  
  128.       // Check for error condition
  129.       IF ! (nChrsRead == nChrsToRead)
  130.          // Error!
  131.          // In order to stay conceptually compatible with the other
  132.          // low-level file functions, force the user to check FERROR()
  133.          // (which was set by the FREAD() above) to discover this fact
  134.          //
  135.          nChrsToRead := 0
  136.       ENDIF
  137.  
  138.       nEOLPos := AT( cDelim, cBuffer )
  139.  
  140.       // Update buffer and current file position
  141.       IF nEOLPos == 0
  142.          cLines  += LEFT( cBuffer, nChrsRead )
  143.          nCurPos += nChrsRead
  144.       ELSE
  145.          cLines  += LEFT( cBuffer, ( nEOLPos + LEN( cDelim ) ) - 1 )
  146.          nCurPos += ( nEOLPos + LEN( cDelim ) ) - 1
  147.          FSEEK( nHandle, nCurPos, FS_SET )
  148.       ENDIF
  149.  
  150.       // Make sure we don't try to read past EOF
  151.       IF (nFileSize - nCurPos) < nLineLength
  152.          nChrsToRead := (nFileSize - nCurPos)
  153.       ENDIF
  154.  
  155.       nCount++
  156.    ENDDO
  157.  
  158.    RETURN cLines
  159.  
  160. /***
  161. *  FileEval( <nHandle>, [<nLineLength>], [<cDelim>], ;
  162. *            <bBlock>, 
  163. *            [<bForCondition>], 
  164. *            [<bWhileCondition>],
  165. *            [<nNextLines>],
  166. *            [<nLine>],
  167. *            [<lRest>] )   --> NIL
  168. *  Apply a code block to lines in a binary file using DBEVAL() as a model.
  169. *  If the intent is to modify the file, the output must be written to a
  170. *  temporary file and copied over the original when done.
  171. *
  172. *  NOTE: <bBlock>, <bForCondition> and <bWhileCondition> are passed a
  173. *        line of the file
  174. *
  175. *  NOTE:  The defaults for nLineLength and cDelim are the same as those
  176. *         for FReadLn()
  177. *
  178. *  NOTE:  The default for the rest of the parameters is that same as for
  179. *         DBEVAL().
  180. *
  181. *  NOTE:  Any past EOF requests (nLine > last line in file, etc.) are ignored
  182. *         and no error is generated.  The file pointer will be left at EOF.
  183. *
  184. *  NOTE:  Check FERROR() to see if it was successful
  185. *
  186. *  Author:  Craig Ogg
  187. *
  188. */
  189. PROCEDURE FileEval( nHandle, nLineLength, cDelim, bBlock, bFor, bWhile, ;
  190.                     nNextLines, nLine, lRest )
  191.    LOCAL cLine
  192.    LOCAL lEOF := .F.
  193.    LOCAL nPrevPos
  194.  
  195.    IF bWhile == NIL
  196.       bWhile := {|| .T.}
  197.    ENDIF
  198.  
  199.    IF bFor == NIL
  200.       bFor := {|| .T.}
  201.    ENDIF
  202.  
  203.    // lRest == .T. means stay where I am.  Anything else means start from
  204.    // the top of the file
  205.    //
  206.    IF ! ( ( VALTYPE(lRest) == 'L' ) .AND. ( lRest == .T. ) )
  207.       FileTop( nHandle )
  208.    ENDIF
  209.  
  210.    BEGIN SEQUENCE
  211.       IF nLine != NIL
  212.          // Process only that one record
  213.          nNextLines := 1
  214.  
  215.          FileTop( nHandle )
  216.  
  217.          IF nLine > 1
  218.             cLine := FReadLn( nHandle, 1, nLineLength, cDelim )
  219.             IF FERROR() != 0
  220.                BREAK
  221.             ENDIF
  222.  
  223.             lEOF := ( cLine == "" )
  224.             nLine--
  225.          ENDIF
  226.  
  227.          // Move to that record (nLine will equal 1 when we are there)
  228.          DO WHILE ( ! lEOF  ) .AND. (nLine > 1)
  229.             cLine := FReadLn( nHandle, 1, nLineLength, cDelim )
  230.             IF FERROR() != 0
  231.                BREAK
  232.             ENDIF
  233.  
  234.             lEOF := ( cLine == "" )
  235.             nLine--
  236.          ENDDO
  237.       ENDIF
  238.  
  239.       // Save starting position
  240.       nPrevPos := FilePos( nHandle)
  241.  
  242.       // If there is more to read from here, get the first line for comparison
  243.       // and potential processing 
  244.       //
  245.       IF ( ! lEOF ) .AND. (nNextLines == NIL .OR. nNextLines > 0)
  246.          cLine := FReadLn( nHandle, 1, nLineLength, cDelim )
  247.          IF FERROR() != 0
  248.             BREAK
  249.          ENDIF
  250.  
  251.          lEOF := ( cLine == "" )
  252.       ENDIF
  253.  
  254.       DO WHILE ( ! lEOF ) .AND. EVAL( bWhile, cLine ) ;
  255.                         .AND. (nNextLines == NIL .OR. nNextLines > 0)
  256.  
  257.          IF EVAL( bFor, cLine )
  258.             EVAL( bBlock, cLine )
  259.          ENDIF
  260.  
  261.          // Save start of line
  262.          nPrevPos := FilePos( nHandle )
  263.  
  264.          // Read next line
  265.          cLine    := FReadLn( nHandle, 1, nLineLength, cDelim )
  266.          IF FERROR() != 0
  267.             BREAK
  268.          ENDIF
  269.  
  270.          lEOF     := ( cLine == "" )
  271.  
  272.          IF nNextLines != NIL
  273.             nNextLines--
  274.          ENDIF
  275.       ENDDO
  276.  
  277.       // If the reason for ending was that I ran past the WHILE or the number
  278.       // of lines specified, back up to the beginning of the line that failed
  279.       // so that there is no gap in processing
  280.       //
  281.       IF ( ! EVAL( bWhile, cLine ) ) .OR. ;
  282.          ( (nNextLines != NIL) .AND. (nNextLines == 0) )
  283.  
  284.          FSEEK( nHandle, nPrevPos, FS_SET )
  285.       ENDIF
  286.    END SEQUENCE
  287.  
  288.    RETURN
  289.  
  290.  
  291. /***
  292. *  FEof( <nHandle> ) --> lBoundary
  293. *  Determine if the current file pointer position is the last
  294. *  byte in the file
  295. *
  296. */
  297. FUNCTION FEof( nHandle )
  298.    RETURN (IF(FileSize(nHandle) == FilePos(nHandle), .T., .F. ))
  299.  
  300.  
  301. /***
  302. *  FWriteLn( <nHandle>, <cString>, [<nLength>], [<cDelim>] ) --> nBytes
  303. *  Write a line to a text file at the current file pointer position. 
  304. *  
  305. *  NOTE: Check FERROR() for the error
  306. *
  307. *  NOTE: nLength defaults to length of entire string + delim, cDelim
  308. *        defaults to CHR(13) + CHR(10)
  309. *
  310. *  NOTE: Return value includes length of delimiter
  311. *
  312. */
  313. FUNCTION FWriteLn( nHandle, cString, nLength, cDelim )
  314.  
  315.    IF cDelim == NIL
  316.       cString += CHR(13) + CHR(10)
  317.    ELSE
  318.       cString += cDelim
  319.    ENDIF
  320.  
  321. RETURN FWRITE( nHandle, cString, nLength )
  322.  
  323. /****
  324. *       Function:  FSize(cFileName) -->NUMERIC
  325. *       Purpose :  Determines file size in bytest
  326. *   Date Created: 03/10/93
  327. */
  328.  
  329. FUNCTION FSize(cFile)
  330.  
  331.    LOCAL nHandle := 0,;
  332.          nSize   := 0,;
  333.          nError
  334.  
  335.    BEGIN SEQUENCE
  336.  
  337.        IF valtype(cFile) <> "C"
  338.           alert("ERROR: Usage: <Fsize> <Filename.ext>;"+GetDosErr(1000))
  339.           BREAK
  340.        ENDIF   
  341.  
  342.        nHandle := fopen( cFile,if(set(_SET_EXCLUSIVE),FO_READWRITE,FO_SHARED))
  343.        IF (nError := ferror()) <> 0
  344.            alert(,,upper(cFile)+"ERROR:" + GetDosErr(nError))
  345.            BREAK
  346.        ENDIF
  347.  
  348.        nSize := FileSize(nHandle)
  349.  
  350.        IF nError == 0
  351.           fclose(nHandle)
  352.        ENDIF
  353.  
  354.    END SEQUENCE
  355.  
  356. RETURN nSize         
  357.  
  358.  
  359.